package cn.jsc.user.service.impl;

import cn.jsc.basic.exception.BusinessException;
import cn.jsc.basic.service.impl.BaseServiceImpl;
import cn.jsc.basic.util.MD5Utils;
import cn.jsc.basic.util.StrUtils;
import cn.jsc.user.constant.UserConstant;
import cn.jsc.user.domain.LoginInfo;
import cn.jsc.user.domain.User;
import cn.jsc.user.dto.RegisterDto;
import cn.jsc.user.mapper.LoginInfoMapper;
import cn.jsc.user.mapper.UserMapper;
import cn.jsc.user.service.IUserServiceI;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * 服务层
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserServiceI {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;
    @Autowired
    private LoginInfoMapper loginInfoMapper;
    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional
    public void add(User user) {
        //设置user信息
        String salt = StrUtils.getComplexRandomString(32);
        user.setSalt(salt);
        String md5pwd = MD5Utils.encrypByMd5(user.getPassword() + salt);
        user.setPassword(md5pwd);

        //添加t_logininfo信息
        LoginInfo loginInfo = user2LoginInfo(user);
        loginInfoMapper.save(loginInfo);

        //添加user信息 - 可以设置登陆信息的id
        user.setLogininfo_id(loginInfo.getId());
        super.add(user);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        //先根据id查user表，为后面删除t_logininfo的信息做准备
        User user = userMapper.loadById(id);

        //删除了t_user的信息
        super.delete(id);

        //删除t_logininfo的信息
        loginInfoMapper.remove(user.getLogininfo_id());
    }

    //@TODO - 现在不做，将来做
    @Override
    @Transactional
    public void update(User user) {
        super.update(user);
    }

    @Override
    @Transactional
    public void phoneRegister(RegisterDto registerDto) {
        //1.校验
        //1.1.空值校验
        String phone = registerDto.getPhone();
        String verifyCode = registerDto.getVerifyCode();
        String password = registerDto.getPassword();
        String passwordRepeat = registerDto.getPasswordRepeat();
        if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(verifyCode)
           || StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordRepeat)){
            throw new BusinessException("信息不能为空！！！");
        }
        //1.2.密码是否一致
        if(!password.equals(passwordRepeat)){
            throw new BusinessException("两次密码不一致！！！");
        }
        //1.3.验证码是否过期 - 或失效
        Object obj = redisTemplate.opsForValue().get(UserConstant.REGISTER_CODE_PREFIX + phone);
        if(obj==null){
            throw new BusinessException("验证码已失效！！！");
        }
        //1.4.验证码是否正确 - 传递过来的和redis中的
        //key - 业务键:手机    value - code:时间戳
        String redisVerifyCode = obj.toString().split(":")[0];
        if(!verifyCode.equalsIgnoreCase(redisVerifyCode)){
            throw new BusinessException("验证码不正确！！！");
        }
        //1.5.手机号是否已经注册过 - 忽略

        //2.保存数据 - 级联操作
        User user=registerDto2User(registerDto);
        LoginInfo info=user2LoginInfo(user);
        //2.1.先保存t_logininfo
        loginInfoMapper.save(info);
        //2.2.再保存t_user
        user.setLogininfo_id(info.getId());
        userMapper.save(user);

    }

    private User registerDto2User(RegisterDto registerDto) {
        User user = new User();
        user.setUsername(registerDto.getPhone());
        user.setPhone(registerDto.getPhone());
        //盐值必须保存在数据库 - 为了登陆
        String salt = StrUtils.getComplexRandomString(32);//随机生成盐值
        user.setSalt(salt);
        //加密加盐的密码
        String md5pwd = MD5Utils.encrypByMd5(registerDto.getPassword() + salt);
        user.setPassword(md5pwd);
        return user;
    }

    private LoginInfo user2LoginInfo(User user) {
        LoginInfo loginInfo = new LoginInfo();
        //按照属性同名原则进行拷贝：username,phone,email,salt,password
        BeanUtils.copyProperties(user,loginInfo);
        loginInfo.setType(1);//1表示用户
        return loginInfo;
    }
}
